#ifndef CONVERSE_CONVERSEABSTRACTCONVERSATION_H
#define CONVERSE_CONVERSEABSTRACTCONVERSATION_H


#include <QObject>
#include <QMap>
#include <QPointer>


namespace Account {
class Member;
}

namespace Network {
class ConnectionJSONRequest;
class HttpRequest;
}

namespace Contact {
class AbstractContact;
}

class MessageRequest;
class MessageEvent;
class MessageGroupRequest;

namespace Converse {

class AbstractMessage;
class MessageContainer;
class MessageGroup;

class AbstractConversation : public QObject
{
    Q_OBJECT
public:
    enum Type {
        PrivateType = 0,
        GroupType = 1,
        UnknownType = -1
    };

    typedef QMap<qint64, AbstractMessage *> Finder;
    typedef QList<MessageGroup *> MessageGroupList;
    typedef QMap<int, MessageRequest *> MessageRequestFinder;
    typedef QMap<int, MessageGroupRequest *> MessageGroupRequestFinder;

public:
    AbstractConversation(qint64 id, Contact::AbstractContact *contact, QObject *parent = 0);
    virtual ~AbstractConversation();

private:
    qint64 m_id;
    Finder m_messageFinder;
    Finder m_sendingFinder;
    MessageRequestFinder m_sendingRequestFinder;
    MessageGroupRequestFinder m_sendingGroupRequestFinder;
    MessageContainer *m_messageContainer;
    QPointer<Contact::AbstractContact> m_ownerContact;

Q_SIGNALS:

    void messageSend(AbstractMessage *message);
    void messageSent(AbstractMessage *message);
    void messageReceived(AbstractMessage *message);
    void messageReadFromLocal(AbstractMessage *message);

    void unreadMessageCountReset();
    void unreadMessageCountChanged(AbstractConversation *conversation, int count);

    void dataAboutToBeInserted(int index, MessageGroup *messageGroup);
    void dataInserted(int index, MessageGroup *messageGroup);

    void dataAboutToBeUpdated(int index, MessageGroup *messageGroup);
    void dataUpdated(int index, MessageGroup *messageGroup);

    void buzz();

private:
    void init();
    void setConnection() const;

private:
    void itemAboutToBeInserted(int index, MessageGroup *messageGroup);
    void itemInserted(int index, MessageGroup *messageGroup);
    void itemAboutToBeUpdated(int index, MessageGroup *messageGroup);
    void itemUpdated(int index, MessageGroup *messageGroup);

private Q_SLOTS:
    void onDataAboutToBeInserted(int index, MessageGroup *messageGroup);
    void onDataInserted(int index, MessageGroup *messageGroup);
    void onDataAboutToBeUpdated(int index, MessageGroup *messageGroup);
    void onDataUpdated(int index, MessageGroup *messageGroup);

private Q_SLOTS:
    void onGetHistoryResponded(Network::HttpRequest *request);

public:
    virtual Type type() const = 0;
    virtual qint64 toId() const = 0;

public:
    void setId(qint64 id);
    qint64 id() const;

    void setContact(Contact::AbstractContact *contact);
    Contact::AbstractContact *contact() const;

    const MessageGroupList &dataItemList() const;
    MessageContainer *messageContainer() const;

    void onGetHistoryMeessageFromLocal(qint64 id,
                                       qint64 conversationId,
                                       qint64 sendingId,
                                       qint64 createdTime,
                                       qint64 receivedTime,
                                       int32_t senderId,
                                       qint64 receiverId,
                                       const QString &text,
                                       int typeMsg,
                                       int isRead,
                                       int isSent);

public:
    int size() const;
    int count() const;

public:
    bool validIndex(int index) const;
    bool contains(MessageGroup *messageGroup) const;
    int indexOf(MessageGroup *messageGroup) const;
    MessageGroup *at(int index) const;

public:
    bool send(const QString &text, qint64 createdTime);
    bool send(const QString &text,
              qint64 createdTime,
              const QString imageID,
              QPixmap pic);

    bool sendGroup(const QString &text, qint64 createdTime);

    void receive(const MessageEvent &event);
    void receive(qint64 id,
                 qint64 sendingId,
                 qint64 createdTime,
                 qint64 senderId,
                 qint64 receiverId,
                 const QString &message);

    bool hasSending(qint64 id) const;

    void postGetHistoryRequest(int messageCount);

public:

};

} // namespace Converse

#endif // CONVERSE_CONVERSEABSTRACTCONVERSATION_H
